﻿using System;
using DDDProjectSample.Domain.Repositories;
using Castle.Facilities.NHibernateIntegration;
using NHibernate;
using System.Collections.Generic;
using NHibernate.Expression;

namespace DDDProjectSample.Infrastructure.Repositories
{
    /// <summary>
    /// Base class for repositories components
    /// </summary>
    public abstract class BaseRepository<T> : IRepository<T>
    {
        private ISessionManager _sessionManager = null;

        /// <summary>
        /// Creates a new instance of class BaseRepository
        /// </summary>
        /// <param name="sessionManager">The Nhibernate Session Manager</param>
        protected BaseRepository(
            ISessionManager sessionManager)
        {
            _sessionManager = sessionManager;
        }

        /// <summary>
        /// Gets the NHibernate SessionManager
        /// </summary>
        protected ISessionManager SessionManager
        {
            get
            {
                return _sessionManager;
            }
        }

        #region IRepository<T> Members

        public T Get(object id)
        {
            using (ISession session = _sessionManager.OpenSession())
            {
                return session.Get<T>(id);
            }
        }

        public T Load(object id)
        {
            using (ISession session = _sessionManager.OpenSession())
            {
                return session.Load<T>(id);
            }
        }

        public void Delete(T entity)
        {
            using (ISession session = _sessionManager.OpenSession())
            {
                session.Delete(entity);
            }
        }

        public void DeleteAll()
        {
            using (ISession session = _sessionManager.OpenSession())
            {
                session.Delete(String.Format("from {0}", typeof(T).Name));
            }
        }

        public void Save(T entity)
        {
            using (ISession session = _sessionManager.OpenSession())
            {
                session.Save(entity);
            }
        }

        public void SaveOrUpdate(T entity)
        {
            using (ISession session = _sessionManager.OpenSession())
            {
                session.SaveOrUpdate(entity);
            }
        }

        public void Update(T entity)
        {
            using (ISession session = _sessionManager.OpenSession())
            {
                session.Update(entity);
            }
        }

        public ICollection<T> FindAll()
        {
            using (ISession session = _sessionManager.OpenSession())
            {
                return session.CreateCriteria(typeof(T))
                                .List<T>();
            }
        }

        public ICollection<T> FindAll(int firstResult, int numberOfResults)
        {
            using (ISession session = _sessionManager.OpenSession())
            {
                return session.CreateCriteria(typeof(T))
                                .SetFirstResult(firstResult)
                                .SetMaxResults(numberOfResults)
                                .List<T>();
            }
        }

        #endregion
    }
}
